﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using CDE_Model;
using XML_Indexing;
using XPath_2;
using XML_Indexing.AnvilIndex;
using XQuery;
using System.IO;
using Common;

namespace XML_Anvil_Console
{
    public class AnvilConsole
    {
        #region Constants

        public static String CONSOLE_VERSION = "0.1";

        #endregion

        #region Fields

        private Boolean _isDeveloperEnvironment;
        private Boolean _isRunning;
        private Collection _currentCollection;
        private Constants _constants;

        #endregion

        #region Constructor

        public AnvilConsole(Boolean isDevEnv) // TODO: Inject custom settings file
        {
            _isDeveloperEnvironment = isDevEnv;
            _constants = new Constants();
            _constants.LoadSettings(); // TODO: Replace with settings file
            _currentCollection = null;
        }

        #endregion

        #region Methods

        public void Run()
        {
            _isRunning = true;
            if (_isDeveloperEnvironment)
            {
                while (_isRunning)
                {
                    Console.Write(" >> ");
                    String input = Console.ReadLine();
                    if (!ParseDeveloperCommands(input))
                    {
                        if (!ParseAnvilCommands(input))
                        {
                            ParseCommands(input);
                        }
                    }
                }
            }
            else
            {
                while (_isRunning)
                {
                    Console.Write(" >> ");
                    String input = Console.ReadLine();
                    if (!ParseDeveloperCommands(input))
                    {
                        if (!ParseAnvilCommands(input))
                        {
                            ParseCommands(input);
                        }
                    }
                }
            }
        }

        private Boolean ParseDeveloperCommands(String input)
        {
            return false;
        }

        private Boolean ParseAnvilCommands(String input)
        {
            String command = input.Split(' ')[0];
            String[] arguments = new String[0];
            if (command.Length < input.Length)
            {
                arguments = input.Substring(command.Length+1).Split(' ');
            }

            if (command.ToLower().Equals("exit"))
            {
                _isRunning = false;
            }
            else if (command.ToLower().Equals("quit"))
            {
                _isRunning = false;
            }
            else if (command.ToLower().Equals("use"))
            {
                try
                {
                    if (Collection.Load(_constants.DefaultDataDirectory + arguments[0], out _currentCollection))
                    {
                        Console.WriteLine("Collection loaded successfully!");
                    }
                    else
                    {
                        Console.WriteLine("Collection was unable to be loaded!");
                    }
                }
                catch (Exception e)
                {
                    Console.WriteLine("One or more documents is not well formed!");
                }
            }
            else if (command.ToLower().Equals("create"))
            {
                if (arguments[0].ToLower().Equals("collection"))
                {
                    String filePath = _constants.DefaultDataDirectory + arguments[1] + ".collection";
                    if (arguments.Length > 2)
                    {
                        filePath = _constants.DefaultDataDirectory + arguments[2];
                    }

                    if (Collection.Create(arguments[1], filePath, out _currentCollection))
                    {
                        Console.WriteLine("Collection created successfully!");
                    }
                    else
                    {
                        Console.WriteLine("Collection creation failed!");
                    }
                }
                else if (arguments[0].ToLower().Equals("document"))
                {
                    Console.WriteLine("Creating documents from the command line is not yet supported");
                }
            }
            else
                return false;

            return true;
        }

        private void ParseCommands(String input)
        {
            if (_currentCollection == null)
            {
                Console.WriteLine("Unable to perform queries because a collection has not been selected");
                return;
            }

            CDE_ModelTest(input);
        }

        private void CDE_ModelTest(String input)
        {
            Collection c = new Collection();

            Document d1 = new Document(c);

            Element d1root = new Element(d1);

            d1root.GenericIdentifier = "Library";

            Element d1e1 = new Element(d1root);
            Element d1e1f1 = new Element(d1e1);
            Element d1e1f2 = new Element(d1e1);

            Element d1e2 = new Element(d1root);
            Element d1e2f1 = new Element(d1e2);
            Element d1e2f2 = new Element(d1e2);
            Element d1e2f3 = new Element(d1e2);

            d1e1.GenericIdentifier = "Book";
            d1e1f1.GenericIdentifier = "Chapter";
            d1e1f2.GenericIdentifier = "Chapter";

            d1e2.GenericIdentifier = "Journal";
            d1e2f1.GenericIdentifier = "Edition";
            d1e2f2.GenericIdentifier = "Edition";
            d1e2f3.GenericIdentifier = "Edition";

            Console.WriteLine(d1.ToString());

            IXMLIndex index = new AnvilIndex();
            index.CreateIndex(d1root);

            XQueryEvaluator evaluator = new XQueryEvaluator(index, input);

            foreach (Element e in evaluator.Evaluate())
            {
                Console.WriteLine(e);
                Console.WriteLine("----------------------------------------------------------");
            }
        }

        public void WriteLine(String input)
        {
            Console.WriteLine(input);
        }

        #endregion
    }
}
